package com.jp.juc.tp;

import cn.hutool.core.date.StopWatch;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * thread pool
 */
public class TpService {


    public void t1() {

        ExecutorService executorService = Executors.newSingleThreadExecutor();

        ExecutorService executorService1 = Executors.newCachedThreadPool();

        ExecutorService executorService2 = Executors.newWorkStealingPool(1);

        ExecutorService executorService3 = Executors.newSingleThreadExecutor();

        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

        CompletionService<Integer> completionService = new ExecutorCompletionService<>(executorService);


    }

    public static void main(String[] args) {

        StopWatch stopWatch = new StopWatch("task List");


        stopWatch.start("f1");
        f1();
        stopWatch.stop();

        stopWatch.start("f2");
        f2();
        stopWatch.stop();

        /*stopWatch.start("f3");
        diy();
        stopWatch.stop();*/


        System.out.println(stopWatch.prettyPrint(TimeUnit.MILLISECONDS));

    }


    public static void f1() {
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        List<Future<Integer>> futureList = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            Future<Integer> future = executorService.submit(TpService::sleepTask);
            futureList.add(future);
        }
        for (Future<Integer> future : futureList) {
            try {
                Integer integer = future.get();
                System.out.println(integer);

            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

    public static void f2() {
        int size = 50;
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        CompletionService<Integer> completionService = new ExecutorCompletionService<>(executorService);
        for (int i = 0; i < size; i++) {
            completionService.submit(TpService::sleepTask);
        }
        for (int i = 0; i < size; i++) {
            try {
                Integer integer = completionService.take().get();
                System.out.println(integer);
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }


    }


    public static Integer sleepTask() {
        int randomInt = RandomUtil.randomInt(1, 10);
        ThreadUtil.sleep(randomInt, TimeUnit.MILLISECONDS);
        return randomInt;
    }


    public static void diy() {
        ExecutorService threadPool = new ThreadPoolExecutor(2, 4, 3,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardPolicy()) {
            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                System.out.println("Ready Execute " + ((Worker) r).getName());
            }

            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                System.out.println("Complete Execute " + ((Worker) r).getName());
            }

            @Override
            protected void terminated() {
                System.out.println("线程池退出 ");
            }
        };
    }

    public void swallowedException() {
        Thread.setDefaultUncaughtExceptionHandler((Thread t, Throwable e) -> {
            System.out.println(t.getName());
            System.out.println(ExceptionUtil.getMessage(e));

        });
        ExecutorService exec = Executors.newSingleThreadExecutor();

        exec.execute(() -> {
            throw new RuntimeException("");
        });
        exec.shutdown();
    }

    public void setDefaultUncaughtExceptionHandler() {
        // Thread.setDefaultUncaughtExceptionHandler();
    }
}
